*compute pooled variance, standard deviation and standard error of variable
*Christoph Siemroth, 2013

prog define pooledvar
    version 11.2

    syntax varlist(min=1 max=1) [if] , by1(varlist) by2(varlist)
	/*by1 defines lower level (first mean), by2 defines higher level (mean of mean)*/

	tempname num lowmean lowvar sumvar groupvarsum groupsum correction data temp
	
quietly save `data'.dta
quietly drop if `varlist'==.
if strpos("`if'","if")>0 {
	quietly keep `if'
	}
bysort `by1': egen `num'=count(`varlist'!=.) //count number of observations
bysort `by1': egen `lowmean'=mean(`varlist') //mean of low level
quietly bysort `by1': egen `lowvar'=sd(`varlist') //sd of low level
quietly replace `lowvar'=`lowvar'^2 //var of low level
quietly bysort `by1': keep if _n==_N //keep only one observation from each low level group
bysort `by2': egen `varlist'meanofmean=mean(`lowmean') //mean of account prob of imp
quietly drop if `num'<2 //insufficient obs to calculate variance
gen `sumvar'=(`num'-1)*`lowvar'
bysort `by2': egen `groupvarsum'=sum(`sumvar') //weighted sum of low level variances
bysort `by2': egen `groupsum'=sum(`num'-1) //sum of number of obs with correction
gen `varlist'pooledvar=`groupvarsum'/`groupsum' //pooled variance
gen `varlist'pooledsd=sqrt(`varlist'pooledvar) //pooled sd
bysort `by2': egen `correction'=sum(1/`num') 
gen `varlist'pooledse=`varlist'pooledsd*sqrt(`correction')
quietly duplicates drop `by2', force
quietly keep `by2' `varlist'meanofmean `varlist'pooledvar `varlist'pooledsd `varlist'pooledse
quietly save `temp'.dta
use `data'.dta, clear
merge m:1 `by2' using `temp'.dta, nogenerate
erase `temp'.dta
erase `data'.dta

end
